package webjs

import (
	"errors"
	"net/http"
	"os"
	"strings"
	"time"

	"gitee.com/haodreams/golib/autoroute/controller"
	"gitee.com/haodreams/golib/easyjs"
	"gitee.com/haodreams/golib/easyjs/taskjs"
	"gitee.com/haodreams/golib/logs"
	"github.com/dop251/goja"
)

// JsController 授权相关的操作
type JsController struct {
	controller.Controller
}

func (m *JsController) check(script string) (vm *goja.Runtime, err error) {
	vm = goja.New()
	cb := taskjs.GetCallBack()
	if cb != nil {
		cb(vm)
	}
	_, err = easyjs.RunScript(vm, "main.js", script)
	if err != nil {
		logs.Warn(err)
		return
	}
	return vm, err
}

// Tasks 同步任务
func (m *JsController) Tasks() {
	// typ := m.GetParam().GetTrimString("type")
	if m.IsPost() {
		tasks := taskjs.GetTasks()
		if tasks == nil {
			m.Error("任务没有初始化")
			return
		}
		m.Page(tasks, nil)
		return
	}
	m.Display()
}

// Check 检查代码
func (m *JsController) Check() {
	param := m.GetParam()
	script := param.GetTrimString("js")
	_, err := m.check(script)
	if err != nil {
		m.Error(err.Error())
		return
	}
	m.Msg("OK")
}

// Test 测试代码
func (m *JsController) Test() {
	now := time.Now()
	param := m.GetParam()
	script := param.GetTrimString("js")

	vm, err := m.check(script)
	if err != nil {
		logs.Warn(err)
		m.Error(err.Error())
		return
	}
	runTime := time.Now()

	//自动检查是否有初始化函数
	test, ok := goja.AssertFunction(vm.Get("TestRun"))
	if ok && test != nil {
		data, err := test(nil)
		if err != nil {
			logs.Warn(err.Error())
			m.Error(err.Error())
			return
		}
		logs.Info("总耗时:", time.Since(now), "运行耗时:", time.Since(runTime))

		m.Msg(data.String())
		return
	}

	//自动检查是否有初始化函数
	setup, ok := goja.AssertFunction(vm.Get("setup"))
	if ok && setup != nil {
		_, err := setup(vm.ToValue(m), vm.ToValue(m.Param))
		if err != nil {
			logs.Warn(err.Error())
			m.Error(err.Error())
		}
	}

	run, ok := goja.AssertFunction(vm.Get("run"))
	if !ok {
		err = errors.New("run  not a function")
		logs.Warn(err)
		m.Error(err.Error())
		return
	}
	data, err := run(nil)
	if err != nil {
		logs.Warn(err)
		m.Error(err.Error())
		return
	}
	logs.Info("总耗时:", time.Since(now), "运行耗时:", time.Since(runTime))

	m.Msg(data.String())
}

// Test 测试代码
func (m *JsController) Download() {
	param := m.GetParam()
	script := param.GetTrimString("js")
	now := time.Now()

	vm, err := m.check(script)
	if err != nil {
		logs.Warn(err)
		m.Error(err.Error())
		return
	}
	runTime := time.Now()

	//自动检查是否有初始化函数
	test, ok := goja.AssertFunction(vm.Get("TestRun"))
	if ok && test != nil {
		data, err := test(nil)
		if err != nil {
			logs.Warn(err.Error())
			m.Error(err.Error())
			return
		}
		logs.Info("总耗时:", time.Since(now), "运行耗时:", time.Since(runTime))

		m.Writer.Header().Add("Content-Disposition", "attachment; filename=result.csv") //fmt.Sprintf("attachment; filename=%s", filename)对下载的文件重命名
		m.Writer.Header().Add("Content-Type", "application/octet-stream")
		m.Writer.WriteString(data.String())
		return
	}

	run, ok := goja.AssertFunction(vm.Get("run"))
	if !ok {
		err = errors.New("run  not a function")
		logs.Warn(err)
		m.Error(err.Error())
		return
	}
	data, err := run(nil)
	if err != nil {
		logs.Warn(err)
		m.Error(err.Error())
		return
	}
	logs.Info("总耗时:", time.Since(now), "运行耗时:", time.Since(runTime))

	m.Writer.Header().Add("Content-Disposition", "attachment; filename=result.csv") //fmt.Sprintf("attachment; filename=%s", filename)对下载的文件重命名
	m.Writer.Header().Add("Content-Type", "application/octet-stream")
	m.Writer.WriteString(data.String())
}

// Save 保存代码
func (m *JsController) Save() {
	fileName := m.GetParam().GetTrimString("name")
	if fileName == "" {
		m.Error("无效的文件名")
		return
	}
	script := m.GetParam().GetTrimString("js")
	if strings.HasSuffix(fileName, ".js") {
		_, err := m.check(script)
		if err != nil {
			m.Error(err.Error())
			return
		}
	}

	err := os.WriteFile(easyjs.GetJsDir()+fileName, []byte(script), 0644)
	if err != nil {
		m.Error(err.Error())
		return
	}
	m.Msg("OK")
}

// File .
func (m *JsController) File() {
	path := easyjs.GetJsDir() + m.GetParam().GetString("path")
	data, err := os.ReadFile(path)
	if err != nil {
		m.Error(err.Error())
	} else {
		m.Msg(string(data))
	}
}

// Tree 标签
type Tree struct {
	ID       string  `json:"id"`
	Label    string  `json:"label"`
	Icon     string  `json:"icon"`
	Children []*Tree `json:"children"`
}

// List 列出所有文件
func (m *JsController) List() {
	path := easyjs.GetJsDir() + m.GetParam().GetString("path")
	fi, err := os.ReadDir(path)
	if err != nil {
		m.Error(err.Error())
		return
	}
	ifs := make([]*Tree, 0, len(fi))
	for _, f := range fi {
		if f.IsDir() {
			cfi, err := os.ReadDir(path + f.Name())
			if err != nil {
				m.Error(err.Error())
				return
			}
			cifs := make([]*Tree, 0, len(cfi))
			for _, cf := range cfi {
				cinf := new(Tree)
				cinf.Label = cf.Name()
				cinf.ID = f.Name() + "/" + cf.Name()
				cifs = append(cifs, cinf)
			}
			ifs = append(ifs, &Tree{
				ID:       f.Name(),
				Label:    f.Name(),
				Children: cifs,
			})

		}else{
			inf := new(Tree)
			inf.Label = f.Name()
			inf.ID = f.Name()
			ifs = append(ifs, inf)
		}

	}
	m.JSON(http.StatusOK, ifs)
}
